﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using Icoders.MarketTracker.Core.MasterData;
using Icoders.MarketTracker.Core.Repository.MasterDataRepositories;
using Icoders.MarketTracker.Core.Validation;
using Icoders.MarketTracker.Data.EF;
using Icoders.MarketTracker.Data.Utils;
using Icoders.MarketTracker.Data.Utils.Caching;

namespace Icoders.MarketTracker.Data.Repository.MasterDataRepositories
{
   public class AreaRepository :RepositoryBase, IAreaRepository
    {
       private AppDataContext _ctx;
       private ICacheProvider _cacheProvider;

       public AreaRepository(AppDataContext ctx, ICacheProvider cacheProvider)
       {
           _ctx = ctx;
           _cacheProvider = cacheProvider;
       }

       public int Save(Area entity)
       {
           ValidationResultInfo vri = Validate(entity);
           if (!vri.IsValid)
           {
               throw new DomainValidationException(vri, "Area Details provided not Valid");
           }
           DateTime date = TimeUtil.GetDateTime();
           TblArea tbl = _ctx.TblArea.FirstOrDefault(s => s.Id == entity.Id);
           if (tbl == null)
           {
               tbl = new TblArea();
               tbl.CreatedOn = date;
               tbl.StatusId = (int)MasterEntityStatus.New;
               _ctx.TblArea.AddObject(tbl);
               tbl.Code = entity.Code;
               tbl.Description = entity.Description;
           }
           tbl.UpdatedOn = date;
           tbl.Name = entity.Name;
           tbl.CityId = entity.CityId;
           _ctx.SaveChanges();
           _cacheProvider.Put(_cacheListKey, _ctx.TblArea.Where(x => x.StatusId != 3).Select(s => s.Id).ToList());
           _cacheProvider.Remove(string.Format(_cacheKey, tbl.Id));
           return tbl.Id;
       }

       public Area GetById(int id)
       {
           Area entity = (Area)_cacheProvider.Get(string.Format(_cacheKey, id));
           if (entity == null)
           {
               var tbl = _ctx.TblArea.FirstOrDefault(s => s.Id == id);
               if (tbl != null)
               {
                   entity = Map(tbl);
                   _cacheProvider.Put(string.Format(_cacheKey, entity.Id), entity);
               }

           }
           return entity;
       }

       public List<Area> GetAll()
       {
           //return _ctx.TblArea.ToList().Where(p => p.StatusId != (int)MasterEntityStatus.Deleted).Select(n => Map(n)).ToList();
           IList<Area> entities = null;
           IList<int> ids = (IList<int>)_cacheProvider.Get(_cacheListKey);
           if (ids != null)
           {
               entities = new List<Area>(ids.Count);
               foreach (int id in ids)
               {
                   Area entity = GetById(id);
                   if (entity != null)
                       entities.Add(entity);
               }
           }
           else
           {
               entities = _ctx.TblArea.Where(x => x.StatusId != 3).ToList().Select(s => Map(s)).ToList();
               if (entities != null && entities.Count > 0)
               {
                   ids = entities.Select(s => s.Id).ToList(); //new List<int>(persons.Count);
                   _cacheProvider.Put(_cacheListKey, ids);
                   foreach (Area p in entities)
                   {
                       _cacheProvider.Put(string.Format(_cacheKey, p.Id), p);
                   }

               }
           }
           return entities.ToList();
       }

       public void Delete(int id)
       {
           var tbl = _ctx.TblArea.FirstOrDefault(s => s.Id == id);
           if (tbl != null)
           {
               tbl.StatusId = (int)MasterEntityStatus.Deleted;
               _ctx.SaveChanges();
               _cacheProvider.Put(_cacheListKey, _ctx.TblArea.Where(x => x.StatusId != 3).Select(s => s.Id).ToList());
               _cacheProvider.Remove(string.Format(_cacheKey, tbl.Id));
           }
       }

       private Area Map(TblArea tblArea)
       {
           return new Area() 
           {
               Id = tblArea.Id,
               Code = tblArea.Code,
               Name = tblArea.Name,
               CityId = tblArea.TblCity.Id,
               CityName = tblArea.TblCity.Name,
               Description = tblArea.Description,
               UpdatedOn = tblArea.UpdatedOn,
               CreatedOn = tblArea.CreatedOn,
               Status = (MasterEntityStatus)tblArea.StatusId

           };
       }

       public ValidationResultInfo Validate(Area objToValidate)
       {
           ValidationResultInfo vri = objToValidate.BasicValidation();
           bool hasDuplicateName = GetAll().Where(v => v.Id != objToValidate.Id)
               .Any(p => p.Name == objToValidate.Name);
           if (hasDuplicateName)
               vri.Results.Add(new ValidationResult("Duplicate Name Found"));
           return vri;
       }

       protected override string _cacheKey
       {
           get { return "Area-{0}"; }
       }

       protected override string _cacheListKey
       {
           get { return "AreaList"; }
       }
    }
}
